/*
 * meituan.com Inc.
 * Copyright (c) 2010-2018 All Rights Reserved.
 */
package jdk.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.Set;

/**
 * <p>
 * 基于NIO的时间服务器
 * </p>
 * @author LvJing
 * @version $Id:TimeServer.java v1.0 2018-11-27 20:16 LvJing Exp $
 */
public class TimeServer {

    public static void main(String[] args) {
        String s = "  ";
        System.out.println(s.length());
        Byte b = 1;
        System.out.println(b.equals(1));
        System.out.println(String.format("ddd{}", "123"));
        // master:commit1
        // master:commit2
        // test:commit3
        // test:commit4
    }

    public class MultiplexerTimeServer implements Runnable {

        private Selector selector;

        private ServerSocketChannel serverChannel;

        private volatile boolean stop;

        public void init(int port) {
            try {
                selector = Selector.open();
                serverChannel = ServerSocketChannel.open();

                serverChannel.configureBlocking(false);
                // backlog为
                serverChannel.socket().bind(new InetSocketAddress(port), 1024);
                serverChannel.register(selector, SelectionKey.OP_ACCEPT);
                System.out.println("TimeServer start in port:" + port);
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }

        public void stop() {
            stop = true;
        }

        @Override
        public void run() {
            while (!stop) {
                try {
                    selector.select(1000);
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> it = selectionKeys.iterator();
                    while (it.hasNext()) {
                        SelectionKey key = it.next();
                        it.remove();
                        try {
                            handleInput(key);
                        } catch (IOException e) {
                            if (key != null) {
                                key.cancel();
                                if (key.channel() != null) {
                                    key.channel().close();
                                }
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (selector != null) {
                try {
                    selector.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void handleInput(SelectionKey key) throws IOException {
            if (key.isValid()) {
                if (key.isAcceptable()) {
                    SocketChannel sc = (SocketChannel) key.channel();
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    int readBytes = sc.read(readBuffer);
                    if (readBytes > 0) {
                        readBuffer.flip();
                        byte[] bytes = new byte[readBuffer.remaining()];
                        readBuffer.get(bytes);
                        String body = new String(bytes, StandardCharsets.UTF_8);
                        System.out.println("TimeServer receive msg:" + body);

                        String response = body.equalsIgnoreCase("QUERY CURRENT TIME") ?
                                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "Error Command";
                        bytes = response.getBytes();
                        ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
                        writeBuffer.put(bytes);
                        writeBuffer.flip();
                        sc.write(writeBuffer);
                    } else if (readBytes < 0){
                        key.cancel();
                        sc.close();
                    } else {
                        // 读到0字节，不做处理
                    }
                }
            }
        }
    }
}
